﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.IsolatedStorage;
using System.Runtime.Serialization;

#if WINDOWS_UWP || NETFX_CORE
using Windows.UI.Xaml.Media.Imaging;
#else
using System.Windows.Media.Imaging;
#endif

namespace Outcoder.Data.ImageCache
{
	/* Based on work by Peter Nowak (http://blogs.compactframework.de/Peter.Nowak/2010/08/12/ldquoIntelligentrdquo+Image+Caching+For+WP+7.aspx)  
		 * and Ingo Rama (http://weblogs.thinktecture.com/ingo/). */
	internal static class ImageCache
	{
		const string imageCacheFile = "ImageCache.data";
		internal static Dictionary<string, ImageCacheItem> imageCache;
		static readonly object imageCacheLock = new object();

		public static BitmapImage GetImage(BitmapImage image)
		{
			string url = image.UriSource.ToString();

#if !WINDOWS_UWP && !NETFX_CORE
			if (Environment.OSVersion.Platform == PlatformID.Win32NT)
			{
				image.UriSource = new Uri(url);
				return image;
			}
#endif

			if (imageCache == null)
			{
				lock (imageCacheLock)
				{
					if (imageCache == null)
					{
						LoadCachedImageInfo();
					}
				}
			}

			if (imageCache.ContainsKey(url))
			{
				if (DateTime.Compare(DateTime.Now, imageCache[url].Expiration) >= 0)
				{
					ImageDownloader.DownloadImage(url, image, imageCache[url]);
				}
				else
				{
					string imageFileName = imageCache[url].LocalFilename;
					IsolatedStorageFile storageFile =
						IsolatedStorageFile.GetUserStoreForApplication();
					IsolatedStorageFileStream imageFile = storageFile.OpenFile(
						imageFileName, FileMode.Open);

#if WINDOWS_UWP || NETFX_CORE
					image.SetSource(imageFile.AsRandomAccessStream());
#elif !SILVERLIGHT
					image.StreamSource = imageFile;
#else
					image.SetSource(imageFile);
#endif
				}
			}
			else
			{
				var item = new ImageCacheItem();
				ImageDownloader.DownloadImage(url, image, item);
			}
			return image;
		}

		static void LoadCachedImageInfo()
		{
			IsolatedStorageFile storageFile =
				IsolatedStorageFile.GetUserStoreForApplication();

			if (!storageFile.FileExists(imageCacheFile))
			{
				imageCache = new Dictionary<string, ImageCacheItem>();
				return;
			}

			bool success = false;

			using (IsolatedStorageFileStream fileStream = storageFile.OpenFile(
				imageCacheFile, FileMode.Open))
			{
				DataContractSerializer serializer = new DataContractSerializer(
					typeof(Dictionary<string, ImageCacheItem>));

				try
				{
					imageCache = (Dictionary<string, ImageCacheItem>)serializer
															.ReadObject(fileStream);
					success = true;
				}
				catch (Exception ex)
				{
					Debug.WriteLine("Unable to read image cache file. " + ex);
				}
			}

			if (!success)
			{
				/* An error occured, so delete the existing cached item. */
				storageFile.DeleteFile(imageCacheFile);
				imageCache = new Dictionary<string, ImageCacheItem>();
			}
		}

		internal static void SaveCachedImageInfo()
		{
			IsolatedStorageFile storageFile =
				IsolatedStorageFile.GetUserStoreForApplication();

			using (IsolatedStorageFileStream fileStream
				= storageFile.CreateFile(imageCacheFile))
			{
				DataContractSerializer serializer = new DataContractSerializer(
					typeof(Dictionary<string, ImageCacheItem>));
				serializer.WriteObject(fileStream, imageCache);
				fileStream.Flush();
			}
		}
	}
}
